﻿#region Using

using System;
using System.Drawing;
using System.Windows.Forms;

#endregion

namespace Dictionary.Tools {
    public interface IParse {
        void ParseString(ref RichTextBox richTextBox, string word);
    }

    // @ Category
    public class ParseCategory : IParse {
        #region IParse Members

        public void ParseString(ref RichTextBox rtb, string word) {
            if (word == null) return;
            if (rtb.Find(word) < 0) return;
            int my1StPosition = rtb.Find(word);
            rtb.SelectionStart = my1StPosition;
            rtb.SelectionLength = word.Length;
            rtb.SelectionFont = new Font("Verdana", 9, FontStyle.Bold);
            rtb.SelectionColor = Color.Red;
        }

        #endregion
    }

    // - Definition
    public class ParseDef : IParse {
        #region IParse Members

        public void ParseString(ref RichTextBox rtb, string word) {
            rtb.AppendText("          ");
            rtb.AppendText(word);
            rtb.AppendText(Environment.NewLine);
        }

        #endregion
    }

    // - Type of word
    public class ParseType : IParse {
        #region IParse Members

        public void ParseString(ref RichTextBox rtb, string word) {
            if (rtb.Find(word) < 0) return;
            int my1StPosition = rtb.Find(word);
            rtb.SelectionStart = my1StPosition;
            rtb.SelectionLength = word.Length;
            rtb.SelectionFont = new Font("Verdana", 9, FontStyle.Bold);
            rtb.SelectionColor = Color.Blue;
        }

        #endregion
    }

    // - Idiom
    public class ParseIdiom : IParse {
        #region IParse Members

        public void ParseString(ref RichTextBox rtb, string word) {
            if (rtb.Find(word) < 0) return;
            int my1StPosition = rtb.Find(word);
            rtb.SelectionStart = my1StPosition;
            rtb.SelectionLength = word.Length;
            rtb.SelectionFont = new Font("Verdana", 9, FontStyle.Bold);
        }

        #endregion
    }

    // - Example
    public class ParseExample : IParse {
        #region IParse Members

        public void ParseString(ref RichTextBox rtb, string word) {
            if (rtb.Find(word) < 0) return;
            int my1StPosition = rtb.Find(word);
            rtb.SelectionStart = my1StPosition;
            rtb.SelectionLength = word.Length;
            rtb.SelectionFont = new Font("Verdana", 9);
            rtb.SelectionColor = Color.Green;
        }

        #endregion
    }

    // - Definition of example
    public class ParseDefExample : IParse {
        #region IParse Members

        public void ParseString(ref RichTextBox rtb, string word) {
            if (rtb.Find(word) < 0) return;
            int my1StPosition = rtb.Find(word);
            rtb.SelectionStart = my1StPosition;
            rtb.SelectionLength = word.Length;
            rtb.SelectionFont = new Font("Verdana", 9);
            rtb.SelectionColor = Color.Gray;
        }

        #endregion
    }

    public class ParseOperationContext {
        #region properties

        public IParse Operation { get; set; }

        #endregion

        #region public methods

        public void ExecuteOperation(ref RichTextBox richTextBox, string word) {
            Operation.ParseString(ref richTextBox, word);
        }

        #endregion
    }

    /// <summary>
    ///   Class for helping parsing text in a richTextBox
    /// </summary>
    public class ParseHelper {
        private static void GetWord(int begin, ref string str, out string word) {
            word = null;
            int i = begin + 1;
            while (str[i] != '|') {
                word += str[i];
                i++;
                if (i > str.Length - 1)
                    return;
            }
        }

        private static void AddWordToRtb(ref RichTextBox rtb, ref string word, string space) {
            if (word == null) return;
            rtb.AppendText(space);
            rtb.AppendText(word);
            rtb.AppendText(Environment.NewLine);
        }

        #region Public Methods

        public static void ParseValue(string value, ref RichTextBox rtb) {
            if (value.Length <= 1)
                return;

            rtb.Clear();
            var parseContext = new ParseOperationContext();
            string word;
            for (int i = 0; i < value.Length - 1; i++) {
                switch (value[i]) {
                    case '@': {
                        GetWord(i, ref value, out word);
                        if (word == null) break;
                        AddWordToRtb(ref rtb, ref word, "   ");
                        parseContext.Operation = new ParseCategory();
                        parseContext.ExecuteOperation(ref rtb, word);
                        i += word.Length + 1;
                    }
                        break;
                    case '-': {
                        GetWord(i, ref value, out word);
                        if (word == null) break;
                        AddWordToRtb(ref rtb, ref word, "        ");
                        i += word.Length + 1;
                    }
                        break;
                    case '*': {
                        GetWord(i, ref value, out word);
                        if (word == null) break;
                        AddWordToRtb(ref rtb, ref word, "      ");
                        parseContext.Operation = new ParseType();
                        parseContext.ExecuteOperation(ref rtb, word);
                        i += word.Length + 1;
                    }
                        break;
                    case '=': {
                        GetWord(i, ref value, out word);
                        if (word == null) break;
                        AddWordToRtb(ref rtb, ref word, "            ");
                        parseContext.Operation = new ParseDefExample();
                        parseContext.ExecuteOperation(ref rtb, word);
                        i += word.Length + 1;
                    }
                        break;
                    case '!': {
                        GetWord(i, ref value, out word);
                        if (word == null) break;
                        AddWordToRtb(ref rtb, ref word, "      ");
                        parseContext.Operation = new ParseIdiom();
                        parseContext.ExecuteOperation(ref rtb, word);
                        i += word.Length + 1;
                    }
                        break;
                    case '+': {
                        GetWord(i, ref value, out word);
                        if (word == null) break;
                        AddWordToRtb(ref rtb, ref word, "            ");
                        parseContext.Operation = new ParseExample();
                        parseContext.ExecuteOperation(ref rtb, word);
                        i += word.Length + 1;
                    }
                        break;
                    case '~':
                        break;
                }
            }
        }

        #endregion
    }
}